/**
 * @file optimizer.cpp
 * @brief IR优化器实现
 * @author VimLVM Team
 * @date 2025
 */

#include "viml/optimizer.h"
#include "viml/vm.h"
#include <chrono>
#include <algorithm>
#include <unordered_set>

namespace viml {

Optimizer::Optimizer(OptimizationLevel level) : level_(level) {}

std::shared_ptr<Function> Optimizer::optimize(const std::shared_ptr<Function>& function) {
    if (level_ == OptimizationLevel::NONE) {
        return function;
    }
    
    auto start = std::chrono::high_resolution_clock::now();
    
    // 创建优化后的函数副本
    auto optimized = std::make_shared<Function>(
        function->name,
        function->parameters,
        function->bytecode,
        function->locals_count
    );
    
    optimized->constants = function->constants;
    optimized->debug_info = function->debug_info;
    
    // 应用优化pass
    if (level_ >= OptimizationLevel::BASIC) {
        constant_folding(optimized);
        dead_code_elimination(optimized);
        peephole_optimization(optimized);
    }
    
    if (level_ >= OptimizationLevel::ADVANCED) {
        common_subexpression_elimination(optimized);
        register_allocation(optimized);
    }
    
    auto end = std::chrono::high_resolution_clock::now();
    stats_.optimization_time_ms = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() / 1000.0;
    
    return optimized;
}

void Optimizer::reset_stats() {
    stats_ = OptimizationStats{};
}

void Optimizer::constant_folding(std::shared_ptr<Function>& function) {
    std::vector<Instruction>& bytecode = function->bytecode;
    std::vector<Value>& constants = function->constants;
    
    for (size_t i = 0; i < bytecode.size(); ++i) {
        Instruction& inst = bytecode[i];
        
        // 检查是否可以进行常量折叠
        if (can_be_optimized(inst)) {
            // 简化的常量折叠 - 实际应该检查操作数是否为常量
            if (inst.b < constants.size() && inst.c < constants.size()) {
                Value left = constants[inst.b];
                Value right = constants[inst.c];
                
                if (left.is_number() && right.is_number()) {
                    double result = 0;
                    double left_num = left.as_number();
                    double right_num = right.as_number();
                    
                    switch (inst.opcode) {
                        case OpCode::ADD: result = left_num + right_num; break;
                        case OpCode::SUB: result = left_num - right_num; break;
                        case OpCode::MUL: result = left_num * right_num; break;
                        case OpCode::DIV: 
                            if (right_num != 0) {
                                result = left_num / right_num;
                            } else {
                                continue; // 除零错误，跳过优化
                            }
                            break;
                        default: continue;
                    }
                    
                    // 创建新的常量
                    size_t new_const_idx = constants.size();
                    constants.emplace_back(result);
                    
                    // 替换为LOAD_CONST指令
                    inst = Instruction(OpCode::LOAD_CONST, inst.a, 0, 0, new_const_idx);
                    stats_.constants_folded++;
                    stats_.instructions_replaced++;
                }
            }
        }
    }
}

bool Optimizer::can_be_optimized(const Instruction& inst) const {
    // 检查指令是否可以进行常量折叠
    switch (inst.opcode) {
        case OpCode::ADD:
        case OpCode::SUB:
        case OpCode::MUL:
        case OpCode::DIV:
        case OpCode::MOD:
            return true;
        default:
            return false;
    }
}

void Optimizer::dead_code_elimination(std::shared_ptr<Function>& function) {
    // TODO: 实现死代码消除
    // 目前为空实现，避免链接错误
}

void Optimizer::common_subexpression_elimination(std::shared_ptr<Function>& function) {
    // TODO: 实现公共子表达式消除
    // 目前为空实现，避免链接错误
}

void Optimizer::peephole_optimization(std::shared_ptr<Function>& function) {
    // TODO: 实现窥孔优化
    // 目前为空实现，避免链接错误
}

void Optimizer::register_allocation(std::shared_ptr<Function>& function) {
    // TODO: 实现寄存器分配
    // 目前为空实现，避免链接错误
}

void Optimizer::inline_cache_optimization(std::shared_ptr<Function>& function) {
    // TODO: 实现内联缓存优化
    // 目前为空实现，避免链接错误
}

bool Optimizer::is_constant(const Value& value) const {
    return value.is_number() || value.is_string() || value.is_boolean();
}

bool Optimizer::is_pure_opcode(OpCode op) const {
    // 检查是否是纯操作码（无副作用）
    switch (op) {
        case OpCode::ADD:
        case OpCode::SUB:
        case OpCode::MUL:
        case OpCode::DIV:
        case OpCode::MOD:
        case OpCode::EQ:
        case OpCode::NE:
        case OpCode::LT:
        case OpCode::LE:
        case OpCode::GT:
        case OpCode::GE:
            return true;
        default:
            return false;
    }
}

// 内联缓存实现
InlineCache::InlineCache() : size_(0) {
    entries_.fill(InlineCacheEntry{});
}

bool InlineCache::add_entry(const InlineCacheEntry& entry) {
    if (size_ >= MAX_CACHE_SIZE) {
        return false;
    }
    entries_[size_++] = entry;
    return true;
}

InlineCacheEntry* InlineCache::get_entry(size_t index) {
    if (index >= size_) {
        return nullptr;
    }
    return &entries_[index];
}

InlineCache::Stats InlineCache::get_stats() const {
    Stats stats;
    stats.total_lookups = 0;
    stats.cache_hits = 0;
    stats.cache_misses = 0;
    
    for (size_t i = 0; i < size_; ++i) {
        stats.total_lookups += entries_[i].hit_count + entries_[i].miss_count;
        stats.cache_hits += entries_[i].hit_count;
        stats.cache_misses += entries_[i].miss_count;
    }
    
    return stats;
}

void InlineCache::clear() {
    size_ = 0;
    entries_.fill(InlineCacheEntry{});
}

// 优化器工厂实现
std::unique_ptr<Optimizer> OptimizerFactory::create(OptimizationLevel level) {
    return std::make_unique<Optimizer>(level);
}

OptimizationLevel OptimizerFactory::from_string(const std::string& str) {
    if (str == "none") return OptimizationLevel::NONE;
    if (str == "basic") return OptimizationLevel::BASIC;
    if (str == "advanced") return OptimizationLevel::ADVANCED;
    return OptimizationLevel::BASIC; // 默认
}

std::string OptimizerFactory::to_string(OptimizationLevel level) {
    switch (level) {
        case OptimizationLevel::NONE: return "none";
        case OptimizationLevel::BASIC: return "basic";
        case OptimizationLevel::ADVANCED: return "advanced";
        default: return "basic";
    }
}

} // namespace viml